import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useAuthStore = defineStore('auth', () => {
  const token = ref<string | null>(localStorage.getItem('token'))
  const user = ref<any>(JSON.parse(localStorage.getItem('user') || 'null'))
  const menus = ref<any[]>([])

  const isAuthenticated = computed(() => !!token.value)

  function setToken(t: string | null) {
    token.value = t
    if (t) localStorage.setItem('token', t)
    else localStorage.removeItem('token')
  }
  function setUser(u: any | null) {
    user.value = u
    if (u) localStorage.setItem('user', JSON.stringify(u))
    else localStorage.removeItem('user')
  }

  async function apiFetch(path: string, opts: RequestInit = {}) {
    const headers: Record<string,string> = { 'Content-Type': 'application/json' }
    if (token.value) headers['Authorization'] = `Bearer ${token.value}`
    const res = await fetch(`/api${path}`, { headers: { ...headers, ...(opts.headers as any) }, ...opts })
    if (!res.ok) throw res
    return res.json()
  }

  async function login(username: string, password: string) {
    const res = await fetch('/api/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username, password })
    })
    if (!res.ok) {
      const body = await res.json().catch(() => ({}))
      throw new Error(body.message || 'Login failed')
    }
    const data = await res.json()
    setToken(data.token)
    setUser(data.user)
    return data
  }

  function logout() {
    setToken(null)
    setUser(null)
    menus.value = []
  }

  async function fetchMe() {
    const data = await apiFetch('/me')
    setUser(data.user)
    return data.user
  }

  async function fetchMenus() {
    // Use the authorized endpoint (role-filtered) for fetching menus used in navigation/top menu
    let data = null
    try {
      data = await apiFetch('/menus/authorized')
    } catch (err) {
      // If fetch fails, we'll fallback to local menus below
      data = null
    }

    // If backend returned menus use them; otherwise provide a sensible local fallback
    if (data && Array.isArray(data.menus) && data.menus.length > 0) {
      menus.value = data.menus || []
    } else {
      // Local fallback menus structure (used when backend has no menu data or in dev)
      menus.value = [
        {
          name: '青少年心理管理',
          children: [
            { name: '筛查与早期识别', url: '/youth/screening' },
            { name: '综合评估', url: '/youth/assessment' },
            { name: '个体化治疗计划', url: '/youth/treatment-plan' },
            { name: '心理治疗与干预', url: '/youth/psychotherapy' },
            { name: '家庭与系统干预', url: '/youth/family-system' },
            { name: '危机与自伤/自杀干预', url: '/youth/crisis' }
          ]
        }
      ]
    }

    return menus.value
  }

  // Fetch direct children for a given parent menu id and merge into menus
  async function fetchChildren(parentId: number) {
    if (!parentId) return []

    // try primary endpoint first, then fallback to query-form endpoint
    let data = await apiFetch(`/menus/${parentId}/children`)    

    const children = (data && (data.children || data)) || []
    // try to find the parent in the current menus and set its children
    const idx = menus.value.findIndex(m => m.id === parentId)
    if (idx !== -1) {
      // ensure reactive replacement
      menus.value[idx] = { ...menus.value[idx], children }
    } else {
      // If parent not found at top level, try to locate recursively and attach children
      function attachRec(nodes: any[]): boolean {
        for (let i = 0; i < nodes.length; i++) {
          if (nodes[i].id === parentId) {
            nodes[i] = { ...nodes[i], children }
            return true
          }
          if (nodes[i].children && nodes[i].children.length) {
            if (attachRec(nodes[i].children)) return true
          }
        }
        return false
      }
      attachRec(menus.value)
    }

    return children
  }

  // Check whether the current user has a function permission for a page.
  // pageUrl: the route/url of the page (e.g. '/users')
  // action: the action name to look for, e.g. '新增','编辑','删除' or a code string
  function hasPermission(menuCode: string, action: string): boolean {
    // super-admin shortcut: allow when user's role looks like admin or role_id === 1    
    if (!menuCode || !action) return false

    const needle = String(action || '').toLowerCase().trim()

    // find the menu node that corresponds to the page (by url/code)
    const findMenu = (nodes: any[], actionToFind: string, mcode: string): any | null => {
      const needle = String(actionToFind || '').toLowerCase().trim()
      for (const n of nodes || []) {
        if (!n) continue
        const name = String(n.name || '').toLowerCase().trim()
        if (name === needle && n.code.substring(0,4)==mcode) return n
        if (n.children && n.children.length) {
          const found = findMenu(n.children, actionToFind,mcode)
          if (found) return found
        }
      }
      return null
    }

    const rootMenu = findMenu(menus.value || [], action,menuCode)    
    
    if (!rootMenu) return false

    // traverse descendants of the found menu and check function nodes that are mapped
    function traverse(node: any): boolean {
      if (!node) return false
      const children = node.children || []

      // check this node itself if it is a function item
      const funcFlag = Number((node.b_function ?? node.is_function ?? node.bFunction ?? node.isFunction ?? 0))
      // interpret mapped only when explicitly false: if backend sets mapped=false explicitly, deny; if mapped is true or undefined, allow
      const mappedExplicitFalse = (typeof node.mapped === 'boolean' && node.mapped === false) || (typeof node.mapped_role_id !== 'undefined' && !node.mapped_role_id)
      if (funcFlag === 1 && !mappedExplicitFalse) {
        const name = String(node.name || '').toLowerCase()
        const code = String(node.code || '').toLowerCase()
        if (name.includes(needle) || code === needle || code.includes(needle)) return true
      }

      for (const c of children) {
        if (traverse(c)) return true
      }
      return false
    }

    return traverse(rootMenu)
  }

  return { token, user, menus, isAuthenticated, login, logout, fetchMe, fetchMenus, fetchChildren, apiFetch, hasPermission }
})

export default useAuthStore
